// vect.cpp -- methods for the Vector class

#include <cmath>
#include "vect.h"   // includes <iostream>

using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;

namespace VECTOR {
    // compute degrees in one radian
    const double Rad_to_deg = 45.0 / atan(1.0);
    // should be about 57.2957795130823

    // private methods
    // calculates magnitude from x and y
    void Vector::set_mag() {
        mag = sqrt(x * x + y * y);
    }

    void Vector::set_ang() {
        if (x == 0.0 && y == 0.0) ang = 0.0;
        else ang = atan2(y, x);
    }

    // set x from polar coordinate
    void Vector::set_x() {
        x = mag * cos(ang);
    }

    // set y from polar coordinate
    void Vector::set_y() {
        y = mag * sin(ang);
    }

    // public methods
    // default constructor
    Vector::Vector() {
        x = y = mag = ang = 0.0;
        mode = RECT;
    }

    // constructor vector from rectangular coordinates if form is r
    // (the default) or else from polar coordinates if form is p
    Vector::Vector(double n1, double n2, VECTOR::Vector::Mode form) {
        SET_Parameter_Vector(n1, n2, form); // includes "vect.h"
    }

    // reset vector from rectangular coordinates if form is
    // RECT (the default) or else from polar coordinates if
    // form is POL
    void Vector::reset(double n1, double n2, VECTOR::Vector::Mode form) {
        SET_Parameter_Vector(n1, n2, form); // includes "vect.h"
    }

    // destructor
    Vector::~Vector() {
    }

    // set to polar mode
    void Vector::polar_mode() {
        mode = POL;
    }

    // set to rectangular mode
    void Vector::rect_mode() {
        mode = RECT;
    }

    // operator overloading
    // add two Vectors
    Vector Vector::operator+(const VECTOR::Vector &b) const {
        return {x + b.x, y + b.y};
    }

    // subtract Vector b from a
    Vector Vector::operator-(const VECTOR::Vector &b) const {
        return {x - b.x, y - b.y};
    }

    // reverse sign of Vector
    Vector Vector::operator-() const {
        return Vector(-x, -y);
    }

    // multiply vector by n
    Vector Vector::operator*(double n) const {
        return Vector(n * x, n * y);
    }

    // friend methods
    // multiply n by Vector a
    Vector operator*(double n, const Vector &a) {
        return a * n;
    }

    // display rectangular coordinates if mode is RECT
    // else display polar coordinates if mode id POL
    std::ostream &operator<<(std::ostream &os, const Vector &v) {
        if (v.mode == Vector::RECT)
            os << "(x,y) = (" << v.x << ", " << v.y << ")";
        else if (v.mode == Vector::POL) {
            os << "(m,a) = (" << v.mag << ", "
               << v.ang * Rad_to_deg << ")";
        } else
            os << "Vector object mode is invalid";
        return os;
    }

    bool Vector::operator==(const Vector &rhs) const {
        return x == rhs.x &&
               y == rhs.y &&
               mag == rhs.mag &&
               ang == rhs.ang &&
               mode == rhs.mode;
    }

    bool Vector::operator!=(const Vector &rhs) const {
        return !(rhs == *this);
    }
} // end namespace VECTOR
